﻿using Alexinea.Autofac.Extensions.DependencyInjection;
using Autofac;
using AutoMapper;
using FluentValidation.AspNetCore;
using LView.CMS.Core.Options;
using LView.CMS.Services;
using LView.CMS.Site.Filter;
using LView.CMS.Site.Validation;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog;
using NLog.Extensions.Logging;
using SQLBuilder.Core;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LView.CMS.Core.Helper;

namespace LView.CMS.Site
{
    public class Startup
    {
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            //指定了文件夹Resources作为存放翻译文件的目录
            services.AddLocalization(options => options.ResourcesPath = "Resources");
            services.Configure<RequestLocalizationOptions>(opts =>
            {
                var supportCultures = new List<CultureInfo>
                {
                    new CultureInfo("vi"),
                    new CultureInfo("en"),
                    new CultureInfo("zh-CN")
                };
                opts.SupportedCultures = supportCultures;
                opts.SupportedUICultures = supportCultures;
            });

            services.Configure<DbOption>("LViewCMS", Configuration.GetSection("DbOpion"));
            //静态资源配置
            services.Configure<List<AssetsOptions>>(Configuration.GetSection("AssetsOptions"));
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
            });
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/Account/Index";
                    options.LogoutPath = "/Account/Logout";
                    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
                });
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(20);
                options.Cookie.HttpOnly = true;
            });
            services.AddAntiforgery(options =>
            {
                options.FormFieldName = "AntiforgeryKey_Gerald";
                options.HeaderName = "X-CSRF-TOKEN-Gerald";
                options.SuppressXFrameOptionsHeader = false;
            });
            #region 添加异常处理过滤器
            services.AddControllers(options => options.Filters.Add(typeof(GlobalExceptionFilter)));
            #endregion
            services.AddControllers();
            services.AddMvc(option =>
            {
                //option.Filters.Add(typeof(GlobalExceptionFilter));
                option.EnableEndpointRouting = false;
            })
                .AddDataAnnotationsLocalization()
                .SetCompatibilityVersion(CompatibilityVersion.Latest)
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                .AddControllersAsServices()
                .AddFluentValidation(fv =>
                {
                    fv.RegisterValidatorsFromAssemblyContaining<ManagerRoleValidation>();
                    fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
                });
            services.AddControllersWithViews().AddRazorRuntimeCompilation();
            services.AddAutoMapper();
            services.AddSQLBuilder(Configuration, "Base", (sql, parameter) =>
            {
                _logger.Info($"SQL语句：{sql}  参数：{JsonHelper.ObjectToJSON(parameter)}");
                return null;
            }, false);
            //services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.RegisterAssemblyTypes(typeof(LMSManagerRoleService).Assembly)
                .Where(t => t.Name.Contains("Service"))
                .AsImplementedInterfaces();


            return new AutofacServiceProvider(builder.Build());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IHostApplicationLifetime applicationLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            ServiceProviderInstance.Instance = app.ApplicationServices;

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSession();
            app.UseAuthentication();
            app.UseForwardedHeaders();
            loggerFactory.AddNLog();

            var requestLocalizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
            app.UseRequestLocalization(requestLocalizationOptions);

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{culture=en}");
            });
        }
    }
}
